//path模块是node.js中处理路径的核心模块。可以很方便的处理关于文件路径的问题。
const path = require("path");
const webpack = require("webpack");
const CompressionWebpackPlugin = require("compression-webpack-plugin"); // 开启gzip压缩， 按需引用
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i; // 开启gzip压缩， 按需写入
const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); // 代码压缩
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin; // 打包分析
//定义环境
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
//join() 将多个参数值合并成一个路径
//const resolve = dir => path.join(__dirname, dir);
function resolve(dir) {
  return path.join(__dirname, dir);
}

//到处对象
module.exports = {
  //部署应用包时的基本 URL publicPath: './',
  publicPath: process.env.NODE_ENV === "production" ? "/site/vue-demo/" : "/", // 公共路径
  //publicPath: "./",//打包的设置
  //publicPath: process.env.NODE_ENV === "production" ? "/site/vue-demo/" : "./", // 公共路径

  //publicPath: process.env.NODE_ENV === 'production' ? './' + config.build.assetsPublicPath : './' + config.dev.assetsPublicPath,
  //当运行 vue-cli-service build 时生成的生产环境构建文件的目录
  outputDir: process.env.outputDir || "dist", // 'dist', 生产环境构建文件的目录

  //放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
  //assetsDir: "assets",
  assetsDir: "static", // 相对于outputDir的静态资源(js、css、img、fonts)目录

  indexPath: "index.html", // 相对于打包路径index.html的路径

  /** 去掉hash
   * 默认情况下，生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。
   * 然而，这也要求 index 的 HTML 是被 Vue CLI 自动生成的。
   * 如果你无法使用 Vue CLI 生成的 index HTML，你可以通过将这个选项设为 false 来关闭文件名哈希*/
  //filenameHashing: false,

  // eslint-loader 是否在保存的时候检查 安装@vue/cli-plugin-eslint有效
  lintOnSave: false, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码

  //是否使用包含运行时编译器的 Vue 构建版本。设置true后你就可以在使用template
  runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
  // 生产环境是否生成 sourceMap 文件 sourceMap的详解请看末尾
  productionSourceMap: !IS_PROD, // 生产环境的 source map

  configureWebpack: config => {
    // 开启 gzip 压缩
    // 需要 npm i -D compression-webpack-plugin
    const plugins = [];
    if (IS_PROD) {
      plugins.push(
        new CompressionWebpackPlugin({
          filename: "[path].gz[query]",
          algorithm: "gzip",
          test: productionGzipExtensions,
          threshold: 10240,
          minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
          deleteOriginalAssets: false // 删除原文件
        })
      );
    }
    config.plugins = [...config.plugins, ...plugins];
    // 移除prefetch插件，避免加载多余的资源
    config.plugins.delete("prefetch");
    /** 删除懒加载模块的 prefetch preload，降低带宽压力(使用在移动端) */
    config.plugins.delete("prefetch").delete("preload");
    config.optimization.minimize(true);

    // 忽略打包配置
    //config.externals = cdn.externals;

    config.plugins.push(
      new webpack.DllReferencePlugin({
        context: __dirname,
        // manifest就是我们第2步中打包出来的json文件
        manifest: require("./vendor-manifest.json")
      })
    );

    config.plugins.push(
      new UglifyJsPlugin({
        uglifyOptions: {
          //生产环境自动删除console
          compress: {
            warnings: false, // 若打包错误，则注释这行
            drop_debugger: true,
            drop_console: true,
            pure_funcs: ["console.log"] // 移除console
          }
        },
        sourceMap: false,
        parallel: true
      })
    );
    // 公共代码抽离
    config.optimization = {
      splitChunks: {
        cacheGroups: {
          vendor: {
            chunks: "all",
            test: /node_modules/,
            name: "vendor",
            minChunks: 1,
            maxInitialRequests: 5,
            minSize: 0,
            priority: 100
          },
          common: {
            chunks: "all",
            test: /[\\/]src[\\/]js[\\/]/,
            name: "common",
            minChunks: 2,
            maxInitialRequests: 5,
            minSize: 0,
            priority: 60
          },
          styles: {
            name: "styles",
            test: /\.(sa|sc|c)ss$/,
            chunks: "all",
            enforce: true
          },
          runtimeChunk: {
            name: "manifest"
          }
        }
      }
    };
  },
  //别名 配置你当前的那个目录需要啥自己加吧
  // eslint-disable-next-line no-dupe-keys
  configureWebpack: {
    resolve: {
      alias: {
        vue$: "vue/dist/vue.esm.js",
        "@": resolve("src"),
        //resolve() 返回绝对路径
        "@c": path.resolve(__dirname, "./src/components"),
        assets: path.resolve(__dirname, "../src/assets")
      }
    }
  },

  chainWebpack: config => {
    config.resolve.symlinks(true); // 修复热更新失效
    // 如果使用多页面打包，使用vue inspect --plugins查看html是否在结果数组中
    config.plugin("html").tap(args => {
      // 修复 Lazy loading routes Error
      args[0].chunksSortMode = "none";
      return args;
    });

    config.externals({
      // cdn：模块名称和模块作用域命名（对应window里面挂载的变量名称）
      vue: "Vue",
      vuex: "Vuex",
      "vue-router": "VueRouter",
      axios: "axios",
      "element-ui": "ELEMENT"
    });

    config.resolve.alias // 添加别名
      .set("@", resolve("src"))
      .set("@assets", resolve("src/assets"))
      .set("@common", resolve("src/common"))
      .set("@components", resolve("src/components"))
      .set("@views", resolve("src/views"))
      .set("@store", resolve("src/store"));
    // 压缩图片
    // 需要 npm i -D image-webpack-loader
    config.module
      .rule("images")
      .use("image-webpack-loader")
      .loader("image-webpack-loader")
      .options({
        //{ bypassOnDebug: true }
        //============ 图片压缩了而且小于多少kb的直接当作背景图处理 ===================
        mozjpeg: { progressive: true, quality: 65 }, // Compress JPEG images
        optipng: { enabled: false }, // Compress PNG images
        pngquant: { quality: [0.65, 0.9], speed: 4 }, // Compress PNG images
        gifsicle: { interlaced: false }, // Compress SVG images
        webp: { quality: 75 }
      });
    // 打包分析, 打包之后自动生成一个名叫report.html文件(可忽视)
    if (IS_PROD) {
      config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
        {
          analyzerMode: "static"
        }
      ]);
    }
  },

  css: {
    requireModuleExtension: false, // 去掉文件名中的 .module
    extract: IS_PROD,
    //是否为 CSS 开启 source map。设置为 true 之后可能会影响构建的性能。
    //sourceMap: false,
    loaderOptions: {
      // 给 less-loader 传递 Less.js 相关选项
      less: {
        // `globalVars` 定义全局对象，可加入全局变量
        globalVars: {
          primary: "#333"
        }
      }
    }
  },
  //跨域代理
  devServer: {
    overlay: {
      // 让浏览器 overlay 同时显示警告和错误
      warnings: true,
      errors: true
    },
    host: "localhost",
    port: 8080, // 端口号
    https: false, // https:{type:Boolean}
    open: true, //配置自动启动浏览器
    hotOnly: true, // 热更新
    // proxy: 'http://localhost:8080'   // 配置跨域处理,只有一个代理
    proxy: {
      //配置多个跨域
      "/api/basis": {
        target: "http://localhost:8080",
        changeOrigin: true,
        ws: true, //websocket支持
        //secure: true,
        pathRewrite: {
          "^/api/basis": ""
        }
      },
      "/api/baidumap": {
        target: "http://api.map.baidu.com/reverse_geocoding",
        changeOrigin: true,
        ws: true, //websocket支持
        secure: false,
        pathRewrite: {
          "^/api/baidumap": ""
        }
      }
    }
  },
  // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用，仅作用于生产构建。
  parallel: require("os").cpus().length > 1,
  // 向 PWA 插件传递选项。
  //随此插件添加的服务工作者仅在生产环境中启用（例如，仅当您运行npm run build或时yarn build）。
  pwa: {}
};
